﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml.Serialization;

namespace dasBlog.Storage
{
    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class QueryArgument
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Value { get; set; }

        public QueryArgument() {}
        public QueryArgument(string name, string value)
        {
            Name = name;
            Value = value;
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public class QueryDescription
    {
        private string _queryName = null;
        private List<QueryArgument> _queryArguments = null;

        [DataMember]
        public string QueryName { get { return _queryName; } }
        [DataMember]
        public List<QueryArgument> Arguments { get { return _queryArguments; } }

        public QueryDescription()
        {
            _queryName = GetType().Name;
            _queryArguments = new List<QueryArgument>();
        }
        
        public QueryDescription(string name, params QueryArgument[] args)
        {
            _queryName = name;
            _queryArguments = new List<QueryArgument>(args);
        }

        private string _asString = null;
        public override string ToString()
        {
            if (_asString == null)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(QueryName).Append(":");
                if (Arguments != null)
                {
                    foreach (QueryArgument arg in Arguments)
                    {
                        sb.Append(arg.Name).Append("=").Append(arg.Value).Append("&");
                    }
                }
                _asString = sb.ToString();
            }
            return _asString;
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class DateRangeQueryDescription : QueryDescription
    {
        public const string Name = "daterange";
        public const string FromArgument = "from";
        public const string ToArgument = "to";

        public DateRangeQueryDescription()
        {
        }

        public DateRangeQueryDescription(DateTime from, DateTime to):
            base(Name,
                 new QueryArgument(FromArgument,from.ToString()), 
                 new QueryArgument(ToArgument,to.ToString()) )
        {
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class DateRangeAndTagQueryDescription : QueryDescription
    {
        public const string Name = "daterangetag";
        public const string FromArgument = "from";
        public const string ToArgument = "to";
        public const string TagArgument = "tag";

        public DateRangeAndTagQueryDescription()
        {
        }

        public DateRangeAndTagQueryDescription(DateTime from, DateTime to, string tag) :
            base(Name,
                  new QueryArgument(FromArgument, from.ToString()),
                  new QueryArgument(ToArgument, to.ToString()),
                  new QueryArgument(TagArgument, tag))
        {
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class IdOnlyQueryDescription : QueryDescription
    {
        public const string Name = "idonly";
        
        public IdOnlyQueryDescription():base(Name)
        {
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class TagQueryDescription : QueryDescription
    {
        public const string Name = "tag";
        public const string TagArgument = "tag";

        public TagQueryDescription()
        {
        }

        public TagQueryDescription(string tag) :
            base( Name, 
                  new QueryArgument(TagArgument, tag))
        {
        }
    }

    [DataContract(Namespace = Names.DataContractNamespace)]
    public sealed class ContentQueryDescription : QueryDescription
    {
        public const string Name = "content";
        public const string SnippetArgument = "snippet";

        public ContentQueryDescription()
        {
        }

        public ContentQueryDescription(string snippet) :
            base(Name,
                  new QueryArgument(SnippetArgument, snippet))
        {
        }
    }
}
